package com.step.mesh.buffer;

import java.nio.FloatBuffer;

import com.step.mesh.Coordinate;
import com.step.utils.BufferUtils;

/**
 * 顶点坐标缓存。如位置坐标，法线向量坐标，纹理坐标
 * @author heop
 *
 */
public class CoordinateBuffer {
	static final int BYTES_PER_PROPERTY = 4;

	private FloatBuffer floatBuffer;
	private int numElements = 0;
	private final int numberPerElement; 
	
	/**
	 * 创建缓存区
	 * @param fb 坐标值缓存
	 * @param elementCount 坐标个数
	 * @param numberPerElement 每个坐标的数值个数
	 */
	public CoordinateBuffer(FloatBuffer fb, int elementCount, int numberPerElement)	{
		floatBuffer = BufferUtils.newFloatBuffer(fb.limit());
		floatBuffer.put(fb);
		numElements = elementCount;
		this.numberPerElement = numberPerElement;
	}
	
	/**
	 * 创建坐标缓存区
	 * @param maxElements
	 * @param numberPerElement
	 */
	public CoordinateBuffer(int maxElements, int numberPerElement){
		int numBytes = maxElements * numberPerElement;
		floatBuffer  = BufferUtils.newFloatBuffer(numBytes);
		this.numberPerElement = numberPerElement;
	}
	
	/**
	 * 坐标数 
	 */
	public int size(){
		return numElements;
	}
	
	/**
	 * 最大容纳的坐标数
	 */
	public int capacity()	{
		return floatBuffer.capacity() / numberPerElement;
	}
	
	/**
	 * 清空缓存
	 */
	public void clear()	{
		floatBuffer.clear();
	}
	
	/**
	 * 获取坐标
	 * @param index 索引位置
	 * @return
	 */
	public Coordinate getCoordinate(int index)	{
		floatBuffer.position(index * numberPerElement);
		if(numberPerElement == 2){
			return new Coordinate( floatBuffer.get(), floatBuffer.get());
		}
		else{
			return new Coordinate( floatBuffer.get(), floatBuffer.get(), floatBuffer.get());
		}
	}
	
	/**
	 * 获取坐标
	 * @param index
	 * @param coordinate 返回的坐标值
	 */
	public void getCoordinate(int index, Coordinate coordinate)	{
		floatBuffer.position(index * numberPerElement);

		if(numberPerElement == 2){
			coordinate.set(floatBuffer.get(), floatBuffer.get());
		}
		else {
			coordinate.set(floatBuffer.get(), floatBuffer.get(), floatBuffer.get());
		}
	}
	
	public float getX(int index){
		floatBuffer.position(index * numberPerElement);
		return floatBuffer.get();
	}
	
	public float getY(int index){
		floatBuffer.position(index * numberPerElement + 1);
		return floatBuffer.get();
	}
	
	public float getZ(int index){
		if(numberPerElement == 2) return 0;		
		floatBuffer.position(index * numberPerElement + 2);
		return floatBuffer.get();
	}
	
	//
	
	public void add(Coordinate coordinate){
		set(numElements, coordinate);
		numElements++;
	}
	
	public void add(float x, float y, float z){
		set(numElements, x,y,z);
		numElements++;
	}
	
	public void add(float x, float y){		
		set(numElements, x,y);
		numElements++;
	}
	
	public void set(int index, Coordinate coordinate)	{
		floatBuffer.position(index * numberPerElement);
		floatBuffer.put(coordinate.getX());
		floatBuffer.put(coordinate.getY());
		if(numberPerElement == 3) floatBuffer.put(coordinate.getZ());
	}

	public void set(int index, float x, float y, float z){
		floatBuffer.position(index * numberPerElement);
		floatBuffer.put(x);
		floatBuffer.put(y);
		if(numberPerElement == 3) floatBuffer.put(z);
	}
	
	public void set(int index, float x, float y){
		if(numberPerElement == 3) throw new RuntimeException("CoordinateBuffer:三维坐标必须提供三个坐标值");
		
		floatBuffer.position(index * numberPerElement);
		floatBuffer.put(x);
		floatBuffer.put(y);
	}
	
	public void setX(int index, float x){
		floatBuffer.position(index * numberPerElement);
		floatBuffer.put(x);
	}
	
	public void setY(int index, float y)	{
		floatBuffer.position(index * numberPerElement + 1);
		floatBuffer.put(y);
	}
	
	public void setZ(int index, float z)	{
		if(numberPerElement == 2) return;
		floatBuffer.position(index * numberPerElement + 2);
		floatBuffer.put(z);
	}

	public FloatBuffer buffer(){
		return floatBuffer;
	}
	
	public void overwrite(float[] coordinates){
		floatBuffer.position(0);
		floatBuffer.put(coordinates);
	}
	
	public CoordinateBuffer clone()
	{
		floatBuffer.position(0);
		CoordinateBuffer c = new CoordinateBuffer(floatBuffer, size(),numberPerElement);
		return c;
	}
}
